
#include "board.h"
#include "sdio.h"

/**
 * SD卡仅支持 512块大小的类型
 */

#define EnterAccessNVICWindow() \
    \
    NVIC_EnableIRQ(SDIO_IRQn);\
    NVIC_EnableIRQ(DMA2_Channel4_5_IRQn)

#define ExitAccessNVICWindow() \
    \
    NVIC_DisableIRQ(SDIO_IRQn);\
    NVIC_DisableIRQ(DMA2_Channel4_5_IRQn)

int bsp_sdcard_init(void)
{
    hsd.Instance = SDIO;
    hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
    hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
    hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE;
    hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
    hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
    hsd.Init.ClockDiv = 2;
    if (HAL_SD_Init(&hsd) != HAL_OK)
    {
        return -1;
    }
    hsd.Init.BusWide = SDIO_BUS_WIDE_4B;
    if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    {
        return -1;
    }
    return 0;
}



/**
 * @retval 0 trans statu
 * @retval 1 busy statu
 * @retval 2 error
 */
int bsp_sdcard_isready(void)
{
    int ret;
    while (hsd.State == HAL_SD_STATE_BUSY) { }
    if (hsd.State != HAL_SD_STATE_READY)
    {
        ret = 2;
        return ret;
    }
    int sta = HAL_SD_GetCardState(&hsd);
    switch (sta)
    {
        case HAL_SD_CARD_TRANSFER:
        {
            ret = 0;
        }
        break;

        case HAL_SD_CARD_RECEIVING:
        case HAL_SD_CARD_PROGRAMMING:
        case HAL_SD_CARD_SENDING:
        {
            ret = 1;
        }
        break;

        default:
        {
            ret = 2;
        }
        break;
    }
    return ret;
}


int bsp_sdcard_led_init(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitTypeDef io;
    io.Mode = GPIO_MODE_OUTPUT_PP;
    io.Pin = SDCARD_LED_PIN;
    io.Speed = GPIO_SPEED_HIGH;
    HAL_GPIO_WritePin(SDCARD_LED_PORT, SDCARD_LED_PIN, GPIO_PIN_SET);
    HAL_GPIO_Init(SDCARD_LED_PORT, &io);
    
    return 0;
}


int bsp_flag_led_init(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitTypeDef io;
    io.Mode = GPIO_MODE_OUTPUT_PP;
    io.Pin = FLAG_LED_PIN;
    io.Speed = GPIO_SPEED_HIGH;
    HAL_GPIO_WritePin(FLAG_LED_PORT, FLAG_LED_PIN, GPIO_PIN_SET);
    HAL_GPIO_Init(FLAG_LED_PORT, &io);
    
    return 0;
}

int bsp_sdcard_read(uint8_t lun, uint8_t *buf, uint32_t BA, uint16_t count)
{
    int ret = 0;

    /* IO_LED */
    bsp_sdcard_led_on();

    do{
        while (bsp_sdcard_isready() != 0) { }

        __HAL_DMA_DISABLE(hsd.hdmarx);
        /* 512 align */
        if (HAL_SD_ReadBlocks_DMA(&hsd, buf, BA, count) != HAL_OK)
        {
            ret = -1;
            break;
        }
        
        while (hsd.State == HAL_SD_STATE_BUSY) { }
        if (hsd.State != HAL_SD_STATE_READY)
        {
            ret = -1;
            break;
        }
    } while(0);
    
    bsp_sdcard_led_off();
    return ret;
}


/**
 * 使用DMA写入，DMA启动时退出函数，此时传输并未完成
 */
int bsp_sdcard_write(uint8_t lun, uint8_t *buf, uint32_t BA, uint16_t count)
{
    int8_t ret = 0;
    
    /* IO_LED */
    bsp_sdcard_led_on();

    do
    {
        while (bsp_sdcard_isready() != 0) { }

        __HAL_DMA_DISABLE(hsd.hdmatx);
        HAL_StatusTypeDef status;
        status = HAL_SD_WriteBlocks_DMA(&hsd, buf, BA, count);
        if (status != HAL_OK)
        {
            ret = -1;
            break;
        }
    } while(0);
    
    bsp_sdcard_led_off();

    return ret;
}

